package com.yy.weixinpay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.google.gson.Gson;
import com.yy.weixinpay.entity.OrderInfo;
import com.yy.weixinpay.entity.RefundInfo;
import com.yy.weixinpay.enums.OrderStatus;
import com.yy.weixinpay.enums.PayType;
import com.yy.weixinpay.enums.wxpay.AliPayTradeState;
import com.yy.weixinpay.service.AliPayService;
import com.yy.weixinpay.service.OrderInfoService;
import com.yy.weixinpay.service.PaymentInfoService;
import com.yy.weixinpay.service.RefundInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import springfox.documentation.spring.web.json.Json;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Slf4j
public class AliPayServiceImpl implements AliPayService {
    @Autowired
    private AlipayClient alipayClient;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired
    private Environment config;
    @Autowired
    private PaymentInfoService paymentInfoService;
    @Autowired
    private RefundInfoService refundInfoService;

    private static final ReentrantLock lock = new ReentrantLock();
    /**
     * 支付发起
     * @param productId
     * @return
     */
    @Override
    public String tradeCreate(Long productId) {
        try{
            log.info("生成订单");
//            OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId);
            OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId, PayType.ALIPAY.getType());
            //调用支付宝支付接口
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            request.setNotifyUrl(config.getProperty("alipay.notify-url"));
            request.setReturnUrl(config.getProperty("alipay.return-url"));
            //封装参数
            JSONObject bizContent = new JSONObject();
            //商户订单号
            bizContent.put("out_trade_no",orderInfo.getOrderNo());
            //支付金额
            BigDecimal totalFee = new BigDecimal(orderInfo.getTotalFee().toString()).divide(new BigDecimal("100"));
            bizContent.put("total_amount",totalFee);
            //订单标题
            bizContent.put("subject",orderInfo.getTitle());
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
            request.setBizContent(bizContent.toString());
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
            if (response.isSuccess()){
                log.info("调用支付宝支付成功，返回结构：{}",response.getBody());
                return response.getBody();
            }else {
                log.info("调用失败");
                throw new RuntimeException("调用支付宝支付失败，状态码为："+response.getCode());
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("创建交易失败");
        }
    }

    /**
     * 支付宝异步通知校验通过，更新订单状态
     * @param params
     */
    @Override
    public void processOrder(Map<String, String> params) {
        log.info("处理订单");
        String outTradeNo = params.get("out_trade_no");
        if (lock.tryLock()){
            try{
                OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(outTradeNo);
                if (!OrderStatus.NOTPAY.getType().equals(orderByOrderNo.getOrderStatus())){
                    return;
                }
                //更新订单状态
                orderInfoService.updateStatusByOrderNo(outTradeNo, OrderStatus.SUCCESS);
                //记录支付日志
                paymentInfoService.createPaymentInfoForAliPay(params);
            }finally {
                lock.unlock();
            }
        }

    }

    /**
     * 取消订单操作
     * @param orderNo
     */
    @Override
    public void cancelOrder(String orderNo) {
        //调用支付宝提供的统一关单接口
        this.closeOrder(orderNo);
        //更新订单状态
        orderInfoService.updateStatusByOrderNo(orderNo,OrderStatus.CANCEL);
    }

    /**
     * 主动查单
     * @param orderNo
     * @return
     */
    @Override
    public String queryOrder(String orderNo) {
        log.info("查询订单接口:{}",orderNo);
        try {
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no",orderNo);
            request.setBizContent(bizContent.toString());
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                log.info("查询成功,返回结果：{}",response.getBody());
                return response.getBody();
            }else {
                log.info("调用失败");
                return null;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("查单接口调用失败");
        }
    }

    /**
     * 检查订单状态
     * @param orderNo
     */
    @Override
    public void checkOrderStatus(String orderNo) {
        log.info("根据订单号核实订单状态：{}",orderNo);
        String result = this.queryOrder(orderNo);
        //订单未创建
        if (result == null){
            log.warn("订单没有创建");
            orderInfoService.updateStatusByOrderNo(orderNo,OrderStatus.CLOSED);
        }
        //解析响应结果
        Gson gson = new Gson();
        HashMap<String,Object> resultMap = gson.fromJson(result, HashMap.class);
        Map alipayTradeQueryResponse = (Map<String, String>) resultMap.get("alipay_trade_query_response");
        String tradeStatus = (String) alipayTradeQueryResponse.get("trade_status");
        if (AliPayTradeState.NOTPAY.getType().equals(tradeStatus)){
            log.warn("订单未支付：{}",orderNo);
            //关闭订单
            this.closeOrder(orderNo);
            //更新订单状态
            orderInfoService.updateStatusByOrderNo(orderNo,OrderStatus.CLOSED);
        }
        if (AliPayTradeState.SUCCESS.getType().equals(tradeStatus)) {
            log.info("订单已经支付");
            //修改状态
            orderInfoService.updateStatusByOrderNo(orderNo,OrderStatus.SUCCESS);
            //添加支付日志
            paymentInfoService.createPaymentInfoForAliPay(alipayTradeQueryResponse);
        }
    }

    /**
     * 退款
     * @param orderNo
     * @param reason
     */
    @Override
    public void refund(String orderNo, String reason) {
        log.info("调用退款API");
        try{
            //创建退款订单
            RefundInfo refundInfo = refundInfoService.createRefundByOrderNo(orderNo,reason);
            //调用统一退单接口
            AlipayTradeRefundApplyRequest request = new AlipayTradeRefundApplyRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no",orderNo);
            BigDecimal refund = new BigDecimal(refundInfo.getRefund().toString()).divide(new BigDecimal("100"));
            bizContent.put("refund_amount",refund);
            bizContent.put("refund_reason",reason);
            request.setBizContent(bizContent.toString());
            AlipayTradeRefundApplyResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                log.info("退款成功:{}",response.getBody());
                //更新订单状态
                orderInfoService.updateStatusByOrderNo(orderNo,OrderStatus.REFUND_SUCCESS);
                //更新退款单
                refundInfoService.updateRefundForAliPay(refundInfo.getRefundNo(),response.getBody(),AliPayTradeState.REFUND_SUCCESS.getType());
            }else {
                log.error("退款失败");
                orderInfoService.updateStatusByOrderNo(orderNo,OrderStatus.REFUND_ABNORMAL);
                refundInfoService.updateRefundForAliPay(refundInfo.getRefundNo(),response.getBody(),AliPayTradeState.REFUND_ERROR.getType());
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 订单号查询退款
     * @param orderNo
     * @return
     */
    @Override
    public String queryRefund(String orderNo) {
        // TODO: 2023/12/5
        //带有用api
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no",orderNo);
        bizContent.put("out_request_no",orderNo);
        request.setBizContent(bizContent.toString());
        try {
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                log.info("查询退款成功");
                return response.getBody();
            }else {
                log.info("查询失败");
                return null;
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 下载支付账单
     * @param billDate
     * @param type
     * @return
     */
    @Override
    public String queryBill(String billDate, String type) {
        try {
            log.info("调用下载订单api");
            AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("bill_type",type);
            bizContent.put("bill_date",billDate);
            request.setBizContent(bizContent.toString());
            AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                log.info("请求下载账单成功:{}",response.getBody());
                //解析返回数据
                Gson gson = new Gson();
                Map<String,Object> resultMap = gson.fromJson(response.getBody(), Map.class);
                Map<String,String> alipayDataDataserviceBillDownloadurlQueryResponse = (Map<String, String>) resultMap.get("alipay_data_dataservice_bill_downloadurl_query_response");
                String billDownloadUrl = alipayDataDataserviceBillDownloadurlQueryResponse.get("bill_download_url");
                return billDownloadUrl;
            }else {
                log.error("调用失败");
                throw new RuntimeException("调用下载账单失败");
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("申请账单失败");
        }
    }

    /**
     * 支付宝关闭订单api
     * @param orderNo
     */
    private void closeOrder(String orderNo) {
        log.info("调用支付宝关闭订单接口");
        try {
            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no",orderNo);
            request.setBizContent(bizContent.toString());
            AlipayTradeCloseResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                log.info("关单成功");
            }else {
                throw new RuntimeException("关单失败");
            }
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }
}
